{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.5.2\n"
     ]
    }
   ],
   "source": [
    "import paddle\n",
    "import paddle.nn.functional as F\n",
    "from paddle.nn import Linear\n",
    "import numpy as np\n",
    "import os\n",
    "import json \n",
    "import random\n",
    "\n",
    "print(paddle.__version__)\n",
    "from paddle.nn import Conv2D,MaxPool2D"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def load_data(mode='train'):\n",
    "    with open('mnist.json') as f:\n",
    "        data = json.load(f)\n",
    "    train_set, val_set, eval_set = data\n",
    "    if mode == 'train':\n",
    "        imgs, labels = train_set[0], train_set[1]\n",
    "    elif mode == 'valid':\n",
    "        imgs, labels = val_set[0], val_set[1]\n",
    "    elif mode == 'eval':\n",
    "        imgs, labels = eval_set[0], eval_set[1]\n",
    "    else:\n",
    "        raise Exception(\"mode can only be one of['train', 'valid', 'eval']\")\n",
    "    print('训练数据集数量:', len(imgs))\n",
    "    imgs_length = len(imgs)\n",
    "    index_list = list(range(imgs_length))\n",
    "    BATCHSIZE = 100\n",
    "\n",
    "    def data_generator():\n",
    "        if mode == 'train':\n",
    "            random.shuffle(index_list)\n",
    "        imgs_list = []\n",
    "        labels_list = []\n",
    "        for i in index_list:\n",
    "            # img=np.array(imgs[i]).astype('float32')\n",
    "            img = np.reshape(imgs[i], [1, 28, 28]).astype('float32')\n",
    "            label = np.reshape(labels[i], [1]).astype('int64')\n",
    "            imgs_list.append(img)\n",
    "            labels_list.append(label)\n",
    "            if len(imgs_list) == BATCHSIZE:\n",
    "                yield np.array(imgs_list), np.array(labels_list)\n",
    "                imgs_list = []\n",
    "                labels_list = []\n",
    "        if len(imgs_list) > 0:\n",
    "            yield np.array(imgs_list), np.array(labels_list)\n",
    "\n",
    "    return data_generator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class LeNetModel(paddle.nn.Layer):\n",
    "    def __init__(self):\n",
    "        super(LeNetModel, self).__init__()\n",
    "        self.conv1 = paddle.nn.Conv2D(in_channels=1, out_channels=6, kernel_size=5, stride=1)\n",
    "        self.pool1 = paddle.nn.MaxPool2D(kernel_size=2, stride=2)\n",
    "        self.conv2 = paddle.nn.Conv2D(in_channels=6, out_channels=16, kernel_size=5, stride=1)\n",
    "        self.pool2 = paddle.nn.MaxPool2D(kernel_size=2, stride=2)\n",
    "        self.fc1 = paddle.nn.Linear(256, 120)\n",
    "        self.fc2 = paddle.nn.Linear(120, 84)\n",
    "        self.fc3 = paddle.nn.Linear(84, 10)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = self.conv1(x)\n",
    "        x = F.relu(x)\n",
    "        x = self.pool1(x)\n",
    "        x = self.conv2(x)\n",
    "        x = F.relu(x)\n",
    "        x = self.pool2(x)\n",
    "        x = paddle.flatten(x, start_axis=1, stop_axis=-1)\n",
    "        x = self.fc1(x)\n",
    "        x = F.relu(x)\n",
    "        x = self.fc2(x)\n",
    "        x = F.relu(x)\n",
    "        x = self.fc3(x)\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train(model):\n",
    "    model.train()\n",
    "\n",
    "    opt = paddle.optimizer.SGD(learning_rate=0.01, parameters=model.parameters())\n",
    "\n",
    "    EPOCH_NUM = 5\n",
    "    train_loader = load_data('train')\n",
    "    valid_loader = load_data('valid')\n",
    "    for epoch_id in range(EPOCH_NUM):\n",
    "\n",
    "        for batch_id, data in enumerate(train_loader()):\n",
    "            images, labels = data\n",
    "            images = paddle.to_tensor(images)\n",
    "            labels = paddle.to_tensor(labels)\n",
    "\n",
    "            predict = model(images)\n",
    "\n",
    "            loss = F.softmax_with_cross_entropy(predict, labels)\n",
    "\n",
    "            avg_loss = paddle.mean(loss)\n",
    "            if batch_id % 200 == 0:\n",
    "                print(\"epoch: {}, batch_id: {}, loss is: {}\".format(epoch_id, batch_id, avg_loss.numpy()))\n",
    "\n",
    "            avg_loss.backward()\n",
    "            opt.step()\n",
    "            opt.clear_grad()\n",
    "\n",
    "        model.eval()\n",
    "        accuracies = []\n",
    "        losses = []\n",
    "        for batch_id, data in enumerate(valid_loader()):\n",
    "            images, labels = data\n",
    "            images = paddle.to_tensor(images)\n",
    "            labels = paddle.to_tensor(labels)\n",
    "\n",
    "            logits = model(images)\n",
    "            pred = F.softmax(logits)\n",
    "\n",
    "            loss = F.softmax_with_cross_entropy(logits, labels)\n",
    "\n",
    "            acc = paddle.metric.accuracy(pred, labels)\n",
    "            accuracies.append(acc.numpy())\n",
    "\n",
    "            losses.append(loss.numpy())\n",
    "        print(\"[validation] accuracy/loss: {}/{}\".format(np.mean(accuracies), np.mean(losses)))\n",
    "    model.train()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练数据集数量: 50000\n"
     ]
    }
   ],
   "source": [
    "train_loader = load_data('train')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练数据集数量: 10000\n"
     ]
    }
   ],
   "source": [
    "valid_loader = load_data('valid')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练数据集数量: 50000\n",
      "训练数据集数量: 10000\n",
      "epoch: 0, batch_id: 0, loss is: [2.4407651]\n",
      "epoch: 0, batch_id: 200, loss is: [0.5913216]\n",
      "epoch: 0, batch_id: 400, loss is: [0.35871223]\n",
      "[validation] accuracy/loss: 0.7826000452041626/0.7435289025306702\n",
      "epoch: 1, batch_id: 0, loss is: [0.90971637]\n",
      "epoch: 1, batch_id: 200, loss is: [0.34056318]\n",
      "epoch: 1, batch_id: 400, loss is: [0.1611243]\n",
      "[validation] accuracy/loss: 0.9465000033378601/0.1803053468465805\n",
      "epoch: 2, batch_id: 0, loss is: [0.11884286]\n",
      "epoch: 2, batch_id: 200, loss is: [0.16120759]\n",
      "epoch: 2, batch_id: 400, loss is: [0.16730072]\n",
      "[validation] accuracy/loss: 0.9601999521255493/0.13425295054912567\n",
      "epoch: 3, batch_id: 0, loss is: [0.21335314]\n",
      "epoch: 3, batch_id: 200, loss is: [0.09274981]\n",
      "epoch: 3, batch_id: 400, loss is: [0.13288955]\n",
      "[validation] accuracy/loss: 0.9645000696182251/0.11788786947727203\n",
      "epoch: 4, batch_id: 0, loss is: [0.13650535]\n",
      "epoch: 4, batch_id: 200, loss is: [0.1684015]\n",
      "epoch: 4, batch_id: 400, loss is: [0.09397918]\n",
      "[validation] accuracy/loss: 0.9683000445365906/0.10804044455289841\n"
     ]
    }
   ],
   "source": [
    "model = LeNetModel()\n",
    "train(model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "paddle.save(model.state_dict(), 'dihongzhi.pdparams')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "from PIL import Image  \n",
    "import numpy as np  \n",
    "import matplotlib.pyplot as plt  \n",
    " \n",
    "im = Image.open('0.jpg').convert('L')    \n",
    "im = im.resize((28, 28), Image.ANTIALIAS)  \n",
    "img = np.array(im).reshape(1, 1, 28, 28).astype('float32')   \n",
    "img = 1.0 - img / 255."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 144x144 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(2, 2))  \n",
    "plt.imshow(img[0][0], cmap=plt.cm.binary)  \n",
    "plt.show()  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "本次预测的数字是： 9\n"
     ]
    }
   ],
   "source": [
    "model = LeNetModel()  \n",
    " \n",
    "params_file_path = 'dihongzhi.pdparams'  \n",
    "param_dict = paddle.load(params_file_path)  \n",
    "model.load_dict(param_dict)  \n",
    " \n",
    "model.eval()  \n",
    "tensor_img = img  \n",
    "\n",
    "results = model(paddle.to_tensor(tensor_img))\n",
    "\n",
    "lab = np.argsort(results.numpy())  \n",
    "print(\"本次预测的数字是：\",lab[0][-1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
